#include <time.h>
#include <rc_gpio/soft_pwm.h>
#include <boost/format.hpp>
#include <fcntl.h>
#include <iostream>
#include <string>
#include <boost/thread/mutex.hpp>
//加载
#define SYSFS_PWM_EXPORT "/sys/class/pwm/pwmchip0/export"
//卸载
#define SYSFS_PWM_UNEXPORT "/sys/class/pwm/pwmchip0/unexport"
//周期
#define SYSFS_PWM_PERIOD "/sys/class/pwm/pwmchip0/pwm%d/period"
//占空比
#define SYSFS_PWM_DUTYCYCLE "/sys/class/pwm/pwmchip0/pwm%d/duty_cycle"
//开关
#define SYSFS_PWM_ENABLE "/sys/class/pwm/pwmchip0/pwm%d/enable"
#define SYSFS_PWM_START "1"
#define SYSFS_PWM_STOP "0"

namespace RC {
    namespace GPIO {
        boost::mutex pwm_mutes;
        void pwm_begin(unsigned int gpio) {
            pwm_free(gpio);
            boost::mutex::scoped_lock lock(pwm_mutes);
            int fd = open(SYSFS_PWM_EXPORT, O_WRONLY);
            if (fd == -1) {
                return;
            }
            std::string export_gpio = std::to_string(gpio);
            write(fd, export_gpio.c_str(), export_gpio.size());
            close(fd);
        }

        void pwm_set_duty_cycle(unsigned int gpio, int dutycycle) {
            boost::mutex::scoped_lock lock(pwm_mutes);
            boost::format fmt(SYSFS_PWM_DUTYCYCLE);
            fmt % gpio;
            std::string targetString = fmt.str();
            int fd = open(targetString.c_str(), O_WRONLY);
            if (fd == -1) {
                return;
            }
            std::string dutycycle_str = std::to_string(dutycycle);
            write(fd, dutycycle_str.c_str(), dutycycle_str.size());
            close(fd);
        }

        void pwm_set_frequency(unsigned int gpio, int freq) {
            boost::mutex::scoped_lock lock(pwm_mutes);
            boost::format fmt(SYSFS_PWM_PERIOD);
            fmt % gpio;
            std::string targetString = fmt.str();
            int fd = open(targetString.c_str(), O_WRONLY);
            if (fd == -1) {
                return;
            }
            std::string dutycycle_str = std::to_string(freq);
            write(fd, dutycycle_str.c_str(), dutycycle_str.size());
            close(fd);
        }

        void pwm_start(unsigned int gpio) {
            boost::mutex::scoped_lock lock(pwm_mutes);
            boost::format fmt(SYSFS_PWM_ENABLE);
            fmt % gpio;
            std::string targetString = fmt.str();
            int fd = open(targetString.c_str(), O_WRONLY);
            if (fd == -1) {
                return;
            }
            write(fd, SYSFS_PWM_START, sizeof(SYSFS_PWM_START));
            close(fd);
        }

        void pwm_stop(unsigned int gpio) {
            boost::mutex::scoped_lock lock(pwm_mutes);
            boost::format fmt(SYSFS_PWM_ENABLE);
            fmt % gpio;
            std::string targetString = fmt.str();
            int fd = open(targetString.c_str(), O_WRONLY);
            if (fd == -1) {
                return;
            }
            write(fd, SYSFS_PWM_STOP, sizeof(SYSFS_PWM_STOP));
            close(fd);
        }

        void pwm_free(unsigned int gpio) {
            boost::mutex::scoped_lock lock(pwm_mutes);
            int fd = open(SYSFS_PWM_UNEXPORT, O_WRONLY);
            if (fd == -1) {
                return;
            }
            std::string export_gpio = std::to_string(gpio);
//            std::cout<<SYSFS_PWM_UNEXPORT<<std::endl;
            write(fd, export_gpio.c_str(), export_gpio.size());
            close(fd);
        }
    }
}